"""
统计解析
"""
from distutils.util import strtobool

from django.apps import apps
from django.db.models import Count, Max, Min, Sum, Avg, StdDev, Variance, DateField, TimeField
from django.db.models.functions import Trunc
from django_filters.conf import settings
from django_filters.constants import ALL_FIELDS
from rest_framework.settings import api_settings
from rest_framework.views import APIView

from super.utils.stat import const


def get_default_value(value):
    try:
        return strtobool(value)
    except ValueError:
        return value


class StatAPIView(APIView):
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    filterset_fields = ALL_FIELDS
    annotate_keyword = {'count': Count, 'max': Max, 'min': Min, 'sum': Sum, 'avg': Avg,
                        'stdDev': StdDev, 'variance': Variance}

    trunc_keyword = {'date': DateField, 'day': DateField,
                     'time': TimeField, 'hour': TimeField, 'minute': TimeField, 'second': TimeField}

    """
    统计解析插件
    """

    def get_queryset(self):
        """
        根据model获取queryset
        @return:
        """
        model_name = self.request.query_params.get('model')
        assert model_name is not None, const.MODEL_IS_REQUIRED
        assert model_name.find('.') > 0, const.MODEL_FORMAT_INCORRECT
        app_model = model_name.split('.')
        app_name = '.'.join(app_model[:len(app_model) - 1])
        _model_name = ''.join(app_model[len(app_model) - 1:])
        assert _model_name != '', const.MODEL_FORMAT_INCORRECT
        app = apps.all_models.get(app_name)
        assert app is not None, const.APP_NAME_INCORRECT.format(app_name, ", ".join(apps.all_models.keys()))
        model = app.get(_model_name)
        assert model is not None, const.MODEL_NAME_INCORRECT.format(_model_name, ", ".join(app.keys()))
        return model.objects.all()

    def filter_queryset(self, queryset):
        """
        支持过滤字段解析
        @param queryset:
        @return:
        """
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset

    def stat(self):
        queryset = self.filter_queryset(self.get_queryset())
        stat_result = self.group_by(queryset)
        # if self.request.query_params.get('format'):
        #     stat_result = self.format_stat(stat_result)
        return stat_result

    def group_by(self, queryset):
        group_name = self.request.query_params.get("group_by")
        assert group_name is not None, const.GROUP_BY_IS_REQUIRED
        order_by = self.request.query_params.get('order_by', '')
        annotate = {key: self.annotate_keyword.get(key)(value)
                    for key, value in self.request.query_params.items() if key in self.annotate_keyword.keys()}
        filters = {key: get_default_value(value) for key, value in self.request.query_params.items()
                   if key.find('__') > -1
                   and key.split('__')[0] in self.annotate_keyword.keys()}
        if group_name.find('__') > -1:
            lookup = group_name.split('__')[0]
            field = group_name.split('__')[1]
            queryset = queryset.annotate(
                **{lookup: Trunc(field, lookup, output_field=self.trunc_keyword.get(lookup)())}).values(lookup)
            if order_by:
                queryset = queryset.order_by(order_by.replace(field, lookup))
        else:
            queryset = queryset.values(group_name)
            if order_by:
                queryset = queryset.order_by(order_by)

        return queryset.annotate(**annotate).filter(**filters)













